<!--
 * @Author: Dorange.Wang
 * @Date: 2021-04-12 15:52:50
 * @LastEditors: wangming
 * @LastEditTime: 2022-02-22 14:25:19
 * @Description: file content
-->
<template>
  <el-dialog
    :visible="showVisible"
    center
    :show-close="false"
    width="900px"
    custom-class="select-modal"
    append-to-body
  >
    <div class="b g3 f16 tl" slot="title">
      <div class="ks-row-between pl15 pr15">
        <span>{{ title }}</span>
        <span class="el-icon-close g9 f26 poi" @click="close"></span>
      </div>
    </div>

    <div class="pl30 pr30">
      <el-row :gutter="24">
        <el-col :span="8">
          <div class="b ks-row-middle h40 mb5">组织架构</div>
          <!-- <el-divider content-position="left">组织架构</el-divider> -->
          <div class="select-modal__content">
            <el-tree
              ref="tree"
              :data="treeDataFilter"
              :expand-on-click-node="false"
              default-expand-all
              node-key="id"
              highlight-current
              :show-checkbox="showCheckbox"
              :check-strictly="checkStrictly"
              @node-click="handleNodeClick"
              @check-change="handleNodeCheck"
            >
              <span
                slot-scope="{ data }"
                :class="{
                  'custom-tree-select__is-disabled': data.disabled,
                }"
              >
                <slot name="node" :data="data">
                  {{ data.name }}
                </slot>
              </span>
            </el-tree>
          </div>
        </el-col>
        <el-col :span="8">
          <div class="ks-row-middle-between h40 mb5">
            <span class="b">可选项</span>
            <el-checkbox
              size="mini"
              @change="changeAll"
              :value="allchecked"
              v-if="filtervlistData.length > 0 && !itemRadio"
              >全选</el-checkbox
            >
          </div>
          <div class="select-modal__content" v-loading="listLoading">
            <el-input
              class="mb5"
              v-model="filterKey"
              placeholder="请输入"
              size="mini"
            ></el-input>
            <empty v-if="listData.length === 0" />

            <!-- 节点单选 -->
            <el-radio-group v-if="itemRadio" v-model="itemRadioKey">
              <el-radio
                v-for="item in filtervlistData"
                :key="item.id"
                :label="item.id"
                :disabled="item.disabled"
                @change="handleItemRadioClick(item)"
              >
                <span
                  name="item"
                  :data="item"
                  :title="item.name"
                  class="select-modal__item-name"
                  >{{ item.name }}</span
                >
              </el-radio>
            </el-radio-group>

            <!-- 节点多选 -->
            <div v-else>
              <el-checkbox-group v-model="itemCheckedKeys">
                <el-checkbox
                  v-for="item in filtervlistData"
                  :key="item.id"
                  :label="item.id"
                  :disabled="item.disabled"
                  @change="handleItemClick($event, item)"
                >
                  <span
                    name="item"
                    :data="item"
                    :title="item.name"
                    class="select-modal__item-name"
                    >{{ item.name }}</span
                  >
                </el-checkbox>
              </el-checkbox-group>
            </div>
          </div>
        </el-col>
        <el-col :span="8">
          <div class="b ks-row-middle h40 mb5">已选项</div>
          <!-- <el-divider content-position="left">已选项</el-divider> -->
          <div class="select-modal__content">
            <template v-if="showCheckbox">
              <div class="select-modal__checked-title">
                已选节点： {{ nodeCheckedData.length }}
              </div>
              <div class="select-modal__checked-ul">
                <empty v-if="nodeCheckedData.length === 0" />
                <div
                  class="select-modal__checked-li"
                  v-for="item in nodeCheckedData"
                  :key="item.id"
                >
                  <slot name="node" :data="item">
                    {{ item.name }}
                  </slot>
                  <i class="el-icon-close" @click="handleNodeDelete(item)"></i>
                </div>
              </div>
              <el-divider />
            </template>

            <div class="select-modal__checked-title">
              已选条目： {{ itemCheckedData.length }}
            </div>
            <div class="select-modal__checked-ul">
              <empty v-if="itemCheckedData.length === 0" />
              <div
                class="select-modal__checked-li"
                v-for="item in itemCheckedData"
                :key="item.id"
              >
                <span
                  name="item"
                  :data="item"
                  :title="item.name"
                  class="select-modal__checked-li-name"
                  >{{ item.name }}</span
                >
                <i class="el-icon-close" @click="handleItemDelete(item)"></i>
              </div>
            </div>
          </div>
        </el-col>
      </el-row>
    </div>

    <div slot="footer" class="tr">
      <el-button @click="close">取 消</el-button>
      <el-button type="primary" @click="submit">确 定</el-button>
    </div>
  </el-dialog>
</template>

<script>
import Empty from "../Empty";
// import { treeToTree } from '@/utils/util'
import { breadFirstTree } from "@/utils/util";
import { cloneDeep } from "lodash";
export default {
  name: "SelectModal",
  components: {
    Empty,
  },
  props: {
    title: {
      type: String,
      default: "选择",
    },
    treeData: {
      type: Array,
      default: () => [],
    },
    // 禁用的节点
    disabledNodeKeys: {
      type: Array,
      default: () => [],
    },
    // 禁用的条目
    disabledItemKeys: {
      type: Array,
      default: () => [],
    },
    showCheckbox: {
      type: Boolean,
      default: false,
    },
    // 在显示复选框的情况下，是否严格的遵循父子不互相关联的做法，默认为 false
    checkStrictly: {
      type: Boolean,
      default: true,
    },
    // 在显示复选框的情况下，父节点选中后子节点禁用
    childDisable: {
      type: Boolean,
      default: false,
    },
    treeNodeChange: {
      type: Function,
      default: () => {
        return Promise.resolve([]);
      },
    },
    autoClose: {
      type: Boolean,
      default: true,
    },
    itemRadio: {
      type: Boolean,
      default: false,
    },
  },

  data() {
    return {
      filterKey: "",
      showVisible: false,
      nodeCheckedData: [], // 选中的节点完整数据
      listData: [], // 可选列表数据
      listLoading: false, // 列表加载loading
      itemCheckedKeys: [], // 选中的列表id（多选）
      itemCheckedData: [], // 选中的列表完整数据（单选、多选）
      itemRadioKey: undefined, // 选中的列表id（单选）
    };
  },

  computed: {
    allchecked() {
      return this.filtervlistData.every(
        (i) => this.itemCheckedKeys.indexOf(i.id) > -1
      );
    },
    filtervlistData() {
      let key = this.filterKey;
      if (!!key) {
        return this.listData.filter((i) => i.name.indexOf(key) > -1);
      } else {
        return this.listData;
      }
    },
    treeDataFilter() {
      if (this.disabledNodeKeys.length > 0) {
        return this.transformTree(this.treeData);
      } else {
        return this.disabledTreeNode(this.treeData);
      }
    },
  },

  methods: {
    changeAll(v) {
      this.filtervlistData.forEach((i) => {
        let index = this.itemCheckedKeys.indexOf(i.id);
        if (v && index === -1) {
          this.itemCheckedKeys.push(i.id);
          this.itemCheckedData.push(cloneDeep(i));
        }
        if (!v && index > -1) {
          this.itemCheckedData.splice(index, 1);
          this.itemCheckedKeys.splice(index, 1);
        }
      });
    },
    disabledTreeNode(tree) {
      return cloneDeep(tree).map((node) => {
        node.disabled = node.disabled || node.accessLevel === "ReadOnly";
        node.children = this.disabledTreeNode(node.children);
        return node;
      });
    },
    transformTree(list, disabled = false) {
      return list.map((item, index, arr) => {
        const nodeDisabled =
          disabled || this.disabledNodeKeys.includes(item.id);
        let subNodeDiabled = nodeDisabled;
        if (this.showCheckbox && this.childDisable) {
          // 禁用当前选中节点的子节点
          subNodeDiabled =
            subNodeDiabled ||
            this.nodeCheckedData.findIndex((node) => node.id === item.id) > -1;
          return {
            ...item,
            disabled: nodeDisabled || item.accessLevel === "ReadOnly",
            children: this.transformTree(item.children, subNodeDiabled),
          };
        }
        // 不禁用当前选中节点的子节点
        return {
          ...item,
          disabled: nodeDisabled || item.accessLevel === "ReadOnly",
          children: this.transformTree(item.children, false),
        };
      });
    },

    init(selectValue) {
      this.listData = [];
      this.nodeCheckedData = [];
      this.$refs.tree && this.$refs.tree.setCheckedKeys([]);
      this.itemCheckedKeys = cloneDeep(selectValue);
      this.itemCheckedData = [];
      this.itemRadioKey = selectValue;
    },

    async open(selectValue = []) {
      if (selectValue instanceof Array) {
        selectValue = selectValue.map((i) => i + "");
      } else {
        selectValue == [selectValue + ""];
      }
      this.filterKey = "";
      this.init(selectValue);
      this.showVisible = true;
      await this.$nextTick();
      if (this.treeData.length > 0) {
        // 默认选中第一个可选的节点
        const node = this.findFirstNodeCanClick();
        if (node && node.id) {
          this.$refs.tree.setCurrentKey(node.id);
          // 拉取节点数据
          await this.handleNodeClick(node);
        }
        this.itemCheckedData = this.listData.filter(
          (i) => selectValue.indexOf(i.id) > -1
        );
      }
    },

    close() {
      this.showVisible = false;
      this.$emit("cancel");
    },

    async handleNodeClick(node) {
      if (node.disabled) {
        return;
      }
      this.listLoading = true;
      try {
        let res = await this.treeNodeChange(node);
        this.listData = res.map((item) => {
          item.id = item.id + "";
          item.disabled =
            item.disabled || this.disabledItemKeys.includes(item.id);
          return item;
        });
      } catch (error) {}
      this.listLoading = false;
    },

    handleNodeCheck(node, checked) {
      if (checked) {
        if (this.showCheckbox && this.childDisable) {
          // 移除当前节点的子节点
          const newChecked = this.nodeCheckedData.filter(
            (ele) => !(ele._parentIds || []).includes(node.id)
          );
          newChecked.push(node);
          this.nodeCheckedData = newChecked;
        } else {
          this.nodeCheckedData.push(node);
        }
      } else {
        this.nodeCheckedData = this.nodeCheckedData.filter(
          (ele) => ele.id !== node.id
        );
      }
      // 这里需要设置tree选中的节点 否则重新渲染tree的时候选中节点会失效
      const nodeCheckedKeys = this.nodeCheckedData.map((ele) => ele.id);
      this.$refs.tree.setCheckedKeys(nodeCheckedKeys);
    },

    handleNodeDelete(item) {
      this.nodeCheckedData = this.nodeCheckedData.filter(
        (ele) => ele.id !== item.id
      );
      const nodeCheckedKeys = this.nodeCheckedData.map((ele) => ele.id);
      this.$refs.tree.setCheckedKeys(nodeCheckedKeys);
    },

    handleItemClick(checked, item) {
      if (checked) {
        this.itemCheckedData.push(item);
      } else {
        this.itemCheckedData = this.itemCheckedData.filter(
          (ele) => ele.id !== item.id
        );
      }
    },

    handleItemRadioClick(item) {
      this.itemCheckedData = [item];
    },

    handleItemDelete(item) {
      this.itemCheckedData = this.itemCheckedData.filter(
        (ele) => ele.id !== item.id
      );
      if (this.itemRadio) {
        this.itemRadioKey = undefined;
      } else {
        this.itemCheckedKeys = this.itemCheckedData.map((ele) => ele.id);
      }
    },

    submit() {
      this.autoClose && (this.showVisible = false);
      this.$emit("ok", {
        node: this.nodeCheckedData,
        item: this.itemCheckedData,
      });
    },
    findFirstNodeCanClick() {
      let firstNode;
      breadFirstTree(
        this.treeDataFilter,
        (node) => {
          if (!node.disabled) {
            firstNode = node;
            return false;
          }
          return true;
        },
        "children"
      );
      return firstNode;
    },
  },
};
</script>

<style lang="scss" scoped>
.select-modal {
  &__content {
    height: 40vh;
    overflow: auto;
    border-top: 1px solid #f1f1f1;
    // margin-top: 10px;
    padding-top: 10px;
  }

  &__checked-title {
    display: flex;
    align-items: center;
    height: 24px;
    font-weight: bold;
  }

  &__checked-ul {
    min-height: 50px;
  }

  &__checked-ul + &__checked-title {
    margin-top: 10px;
  }

  &__checked-li {
    display: flex;
    align-items: center;
    height: 24px;
    justify-content: space-between;

    ::v-deep .select-modal__checked-li-name {
      width: 100px;
      flex: 1;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
    }

    & > i {
      margin-right: 10px;
      cursor: pointer;
      color: #1890ff;
      font-weight: bold;
    }
  }
  .el-checkbox-group,
  .el-radio-group {
    .el-checkbox,
    .el-radio {
      display: block;
      margin-right: 0;
      display: flex;
      align-items: center;
      height: 24px;

      ::v-deep .el-checkbox__label {
        width: 100px;
        flex: 1;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
      }
    }
  }
}
</style>
<style lang="scss">
.select-modal {
  .el-dialog__body {
    padding-top: 0 !important;
  }
}
</style>
